|DÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ |Dº |5The Happy Hacker |DºÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ |DÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ^C^1Machine Language to Turbo Pascal Inline ^Cby ^CAshraf Maher Kaiser Turbo Pascal allows the user to mix Pascal with Machine Language by using the Inline statement, which allows the insertion of the machine code in numeric format in the Turbo program. The process of writing the Inline statements is tedious and error prone if done manually. This utility reads in a .COM file and creates a file with equivalent Turbo Pascal Inline statement. Just write the function in assembly, assemble and link it and convert it to a .COM or .BIN file with the EXE2BIN utility (or you can input it using DEBUG), then run this utility to get a Turbo procedure (or function) with equivalent Inline statements. The user supplies the name of the file to be converted to Turbo Inline statements, and the name of the file to be created. The user may choose whether or not to have the offsets of the instructions printed, which may be useful for tracing branches in the code and data locations. The program works by determining the input file size, and writes out a file containing commands for DEBUG (the debugger that comes with MS-DOS) to disassemble the correct size of code. DEBUG is then invoked from within the program and its input is redirected from the file (INDEBUG) which contains the commands and its output is redirected to the file (OUTDEBUG). Finally, the output file (OUTDEBUG) is processed to create the Turbo file containing Inline statements. Therefore, the files COMMAND.COM and DEBUG.COM should be accessible to the program while running, and the program will prompt you for their drive letter and path. Note that you will need plenty of disk space for the input and output files. The program then asks for the procedure or function name of the routine. Then it asks for any global variable references for your procedure or function. Next, it asks for local variables, that is any variables accessed by the assembly language routine. Finally, it asks for the parameters to be passed to the procedure. After entering the data for each routine, you will have a chance to change any of the data associated with each section. If no type is entered with a local variable or a passed parameter, then the next type entered will be used unless you change from VAR to value or vice versa. The key to this program working properly is in the coding of your assembler program. Global variables should be placed in the data segment. The type of variable determines its offset as assembled in the binary file and will correspond to the offset from start of the data segment in the assembly file. The variables appear in the OUTDEBUG file as 4 digit offsets enclosed in brackets, i.e. [0000],[0002]. If the type of variable specified in ML2INLINE does not match the number of bytes defined in the assembler program, then ML2INLINE will not properly place the Turbo global variable names in the inline program. Here is an example of assembler code with the associated Turbo code. data segment test1 db ? test1: byte; test2 dw ? test2: integer; test3 db 81 dup(?) test3: string[80]; { specify as 81 bytes } test4 db ? test4: byte; { in ML2INLINE } data ends Local variables and passed parameters are referenced in the inline code from the base pointer [BP]. Local variables should be coded in the assembly listing as negative offsets to BP. The first variable is coded as [BP-1], the second as [BP-2], etc. Parameters passed to the inline procedure should be passed as positive offsets to BP. The first variable that Turbo pushes on the stack is coded as [BP+1], the second as [BP+2], etc. The ML2INLINE entry routine assumes a 1 byte offset to the pointer, but if you are passing more than 255 bytes to the inline routine or accessing more than 255 bytes of local variables, then you should add 256 to the parameter number in the assembly code for that and all variables that follow it and change the 2 byte offset reference in the ML2INLINE entry to yes. This is because the machine code is different for a one byte offset and a two byte offset. Remember that Turbo passes the last variable in its parameter list first, and the first one last, but local variables are assigned in normal order. The program follows this convention to keep you reminded of this. Here is an example of Turbo code and what ML2INLINE expects to see when it replaces the text. Procedure Test (Up, Down: byte; Across: integer); var i,j: byte; k: integer; ML2INLINE will replace [BP+3] with Down and >Up in the inline code. If your routine accesses global variables, then you should place 2 nops at the end of the code segment. ML2INLINE will detect these and you can end the processing without the data segment bytes at the end of the inline code. ML2INLINE will process multiple procedures. Each procedure should be separated by at least 2 nops. The program detects 2 nops as the end of a procedure, so that you can write several procedures in one file. Global variables are accessed throughout all the procedures, but each procedure will have its own local variables and parameters. If you have nested procedures, you will have to place the proper amount of NOPs in your assembly code in order to get the correct compiled addresses. When Turbo compiles procedures, it places instructions at the beginning and end of every procedure and function. Turbo places 7 bytes of code before every procedure and 7 bytes after if you pass no parameters to the procedure. If you pass any parameters to the procedure, Turbo places 9 bytes after it. If you declare local variables to the procedure, Turbo places 1 extra byte of code if the total size of the local variables is 1 byte, 2 extra bytes if the size is 2 bytes, 3 extra bytes if the size is 3 to 255 bytes and 4 extra bytes if the size is greater than 256 bytes. This will enable you to calculate the correct number of NOPs to put in your assembly language code. Since, there is not much extra disk space on this disk, you should run it from outside the BIG BLUE DISK menu. To run this program outside the BIG BLUE DISK menu, type ^1ML2INLIN^0. DISK FILES USED BY THIS PROGRAM: ^FML2INLIN.COM ^FML2INLIN.CFG